package com.youth.youthservice.service.impl;

import com.alibaba.nacos.client.naming.utils.StringUtils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.vod.model.v20170321.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youth.commonutils.BeanCopyUtils;
import com.youth.commonutils.R;
import com.youth.servicebase.exceptionhandler.GlobalException;
import com.youth.youthservice.client.VodClient;
import com.youth.youthservice.entity.EduVideo;
import com.youth.youthservice.entity.chapter.VideoVo;
import com.youth.youthservice.mapper.EduVideoMapper;
import com.youth.youthservice.service.EduVideoService;
import com.youth.youthservice.utils.AliyunVodSDKUtils;
import com.youth.youthservice.utils.ConstantPropertiesUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程视频 服务实现类
 * </p>
 *
 * @author CM
 * @since 2023-4-30
 */
@Service
@Slf4j
public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {


    @Autowired
    private VodClient vodClient;    // 用于远程调用阿里云sdk删除云端小节视频

    /*对代理对象做初始化*/
//    private

    /*根据章节id获取对应小节Video*/
    @Override
    public List<VideoVo> GetVideoVoList(String courseId, String chapterId) {
        LambdaQueryWrapper<EduVideo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EduVideo::getCourseId, courseId)
                .eq(EduVideo::getChapterId, chapterId);
        List<EduVideo> list = list(queryWrapper);
        List<VideoVo> res = BeanCopyUtils.copyBeanToList(list, VideoVo.class);
        return res;
    }

    /*新增小节*/
    @Override
    public R insert(EduVideo video) {
        /*判断当前章节中是否存在同名小节目*/
        LambdaQueryWrapper<EduVideo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EduVideo::getChapterId, video.getChapterId())
                .eq(EduVideo::getTitle, video.getTitle());
        if (count(queryWrapper) != 0) {
            throw new GlobalException(20003, "当前章节已存在同名小节，请修改!");
        }
        /*如果该小节上传了视频*/
        if (StringUtils.isNotEmpty(video.getVideoSourceId())) {
            video.setStatus("Draft");  // 说明视频上传成功
        }
        if (!save(video)) {
            throw new GlobalException(20003, "小节添加失败！");
        }
        return R.ok();
    }


    private static final ExecutorService threadPoolExecutor = Executors.newSingleThreadExecutor();

    /*根据章节Id删除对应小结*/
    @Override
    @Transactional(rollbackFor = GlobalException.class)
    public void deleteByChapterId(String chapterId) {
        EduVideoService currentProxy = (EduVideoService) AopContext.currentProxy();
        /*先删除章节下的所有小节*/
        QueryWrapper<EduVideo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("chapter_id", chapterId);
        List<EduVideo> videoList = list(queryWrapper);
        // 删除小节信息
        videoList.stream().forEach(eduVideo -> {
            currentProxy.removeVideo(eduVideo.getId());
        });
    }

    /*删除视频后更新小节信息*/
    @Override
    public R updateSourceVideo(String id) {
        UpdateWrapper<EduVideo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", id);
        updateWrapper.set("size", 0)
                .set("status", "Empty")
                .set("video_source_id", null)
                .set("video_original_name", null);
        EduVideo video = getById(id);
        if (update(video, updateWrapper)) {
            log.warn("课程已删除，但数据库未同步更新小节信息！");
            return R.error();
        }
        return R.ok();
    }

    /*根据小节id删除小节和其中的视频*/
    @Override
    @Transactional(rollbackFor = GlobalException.class)
    public R removeVideo(String VideoId) {
        EduVideo video = getById(VideoId);
        /*如果该小节上传了视频，调用远程方法删除小节视频*/
        if (Objects.nonNull(video.getVideoSourceId())) {
            try {
                vodClient.removeAliVideo(video.getVideoSourceId());
            } catch (Exception e) {
                log.error("远程删除云端视频失败：, stack=>{}", e.getMessage());
            }
        }
        /*删除小节信息*/
        if (!removeById(VideoId)) {
            throw new GlobalException(20001, "小节数据库信息删除失败！");
        }
        return R.ok();
    }

    @Override
    public R getVideoAsc(String videoId) {
        EduVideo video = getById(videoId);
        if (StringUtils.isEmpty(video.getVideoSourceId())) {
            return R.ok();
        } else {
            /*根据videoId拿到凭证信息*/
            DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(ConstantPropertiesUtil.ACCESS_KEY_ID, ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
            request.setVideoId(video.getVideoSourceId());
            GetVideoPlayAuthResponse acsResponse = null;
            try {
                acsResponse = client.getAcsResponse(request);
            } catch (ClientException e) {
                throw new RuntimeException(e);
            }
            String auth = acsResponse.getPlayAuth();
            System.out.println(auth);
            return R.ok().data("vid", video.getVideoSourceId()).data("auth", auth);
        }
    }

    @Override
    public R getPlayUrl(String videoId) {
        EduVideo video = getById(videoId);
        if (StringUtils.isEmpty(video.getVideoSourceId())) {
            return R.ok();
        } else {
            DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(ConstantPropertiesUtil.ACCESS_KEY_ID, ConstantPropertiesUtil.ACCESS_KEY_SECRET);
            GetPlayInfoRequest request = new GetPlayInfoRequest();
            request.setVideoId(video.getVideoSourceId());
            // request.setAdditionType();
            GetPlayInfoResponse response = null;
            try {
                response = client.getAcsResponse(request);
            } catch (ClientException e) {
                throw new RuntimeException(e);
            }
            String playURL = response.getPlayInfoList().get(0).getPlayURL();
            System.out.println(playURL);
            return R.ok().data("playUrl", playURL);
        }
    }

}
